<?php
/**
 * SocialEngine
 *
 * @category   Application_Core
 * @package    Core
 * @copyright  Copyright 2006-2010 Webligo Developments
 * @license    http://www.socialengine.net/license/
 * @version    $Id: FormSequence.php 7904 2010-12-03 03:36:14Z john $
 * @author     John
 */

/**
 * @category   Application_Core
 * @package    Core
 * @copyright  Copyright 2006-2010 Webligo Developments
 * @license    http://www.socialengine.net/license/
 */
class Core_Controller_Action_Helper_FormSequence
  extends Zend_Controller_Action_Helper_Abstract
{
  protected $_plugins = array();

  protected $_order = array();

  protected $_needsSort = false;

  protected $_completeAction = array();

  protected $_registry;

  public function direct()
  {
    // If not posting, reset all
    if( !$this->getActionController()->getRequest()->isPost() ) {
      $this->resetAll();
    }

    // Call init
    $this->initAll();

    // Process
    $this->doSubmit();
    $this->doView();
    return $this->doProcess();
  }

  public function getRegistry()
  {
    if( null === $this->_registry ) {
      $this->_registry = new stdClass();
    }

    return $this->_registry;
  }

  public function setPlugin(Core_Plugin_FormSequence_Interface $plugin, $order = 100)
  {
    $class = get_class($plugin);
    $this->_plugins[$class] = $plugin;
    $this->_order[$class] = $order;
    $this->_needsSort = true;
    $plugin->setRegistry($this->getRegistry());
    return $this;
  }

  public function getPlugin($class)
  {
    return @$this->_plugins[$class];
  }

  public function getPlugins()
  {
    $this->_sortPlugins();
    return $this->_plugins;
  }

  public function setPluginOrder($class, $order = 100)
  {
    if( isset($this->_plugins[$class]) )
    {
      $this->_order[$class] = $order;
      $this->_needsSort = true;
    }
    return $this;
  }

  public function clearPlugins()
  {
    $this->_plugins = array();
    $this->_order = array();
    $this->_needsSort = false;
    return $this;
  }

  protected function _sortPlugins()
  {
    if( $this->_needsSort )
    {
      $this->_needsSort = false;
      asort($this->_order);

      // Experimental
      $plugins = array();
      foreach( $this->_order as $class => $order )
      {
        $plugins[$class] = $this->_plugins[$class];
      }
      $this->_plugins = $plugins;
    }
  }

  public function initAll()
  {
    foreach( $this->getPlugins() as $plugin ) {
      if( method_exists($plugin, 'init') ) {
        $plugin->init();
      }
    }

    return $this;
  }

  public function resetAll()
  {
    foreach( $this->getPlugins() as $plugin ) {
      $plugin->resetSession();
    }

    return $this;
  }



  // Processing

  public function doSubmit()
  {
    if( $this->getActionController()->getRequest()->isPost() )
    {
      foreach( $this->getPlugins() as $plugin )
      {
        if( $plugin->isActive() )
        {
          $plugin->onSubmit($this->getActionController()->getRequest());
          return $plugin;
        }
      }
    }

    return false;
  }

  public function doView()
  {
    foreach( $this->getPlugins() as $plugin )
    {
      if( $plugin->isActive() )
      {
        $plugin->onView();
        $this->getActionController()->view->script = $plugin->getScript();
        $this->getActionController()->view->form = $plugin->getForm();
        $this->getActionController()->view->title = $plugin->getTitle();
        return $plugin;
      }
    }

    return false;
  }

  public function doProcess()
  {
    // Check if we are all done
    $done = true;
    foreach( $this->getPlugins() as $plugin )
    {
      if( $plugin->isActive() )
      {
        $done = false;
      }
    }

    // Process
    if( $done )
    {
      $db = Engine_Db_Table::getDefaultAdapter();
      $db->beginTransaction();

      try
      {
        foreach( $this->getPlugins() as $plugin )
        {
          $plugin->onProcess();
        }

        $db->commit();
      }
      catch( Exception $e )
      {
        $db->rollBack();
        throw $e;
      }

      // Remove session data
      foreach( $this->getPlugins() as $plugin )
      {
        $plugin->getSession()->unsetAll();
      }

    }

    return $done;
  }

  protected function _forward($action, $controller = null, $module = null, array $params = null)
  {
    $request = $this->getActionController->getRequest();

    if (null !== $params) {
      $request->setParams($params);
    }

    if (null !== $controller) {
      $request->setControllerName($controller);

      // Module should only be reset if controller has been specified
      if (null !== $module) {
        $request->setModuleName($module);
      }
    }

    $request->setActionName($action)
      ->setDispatched(false);
  }
}